/* Andreas Baum
 * ClientThread.java
 * Handles the interaction of the java client with the central server
 * CS 78 - Networks
 */

/* 
 * The notion of "server" in this project can lead to confusion: 
 * Indeed, it is employed with two separate meanings.
 * 1. The central login server
 * 2. The "server" side of the iTunes connection to which another proxy connect
 * , and which allows another user to access the user's iTunes library.
 */

package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import jbpClientConnector.JBPClientConnector;

public class ClientThread extends Thread {
	private Socket socket = null;
	private PrintWriter out = null;
	private BufferedReader in = null;
	private boolean disconnect = false;

	public ClientThread(Socket socket) throws IOException {
		super("ClientThread");
		this.socket = socket;
		
		

		// establish the keyboard input stream:
		BufferedReader keyboardIn =
			new BufferedReader(
					new InputStreamReader( System.in ) );

		try {
			// establish in and out streams for communication with server
			out = new PrintWriter(socket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(
					socket.getInputStream()));
		} catch (IOException e) {
			e.printStackTrace();
		}

		// start listening to the socket
		this.start();

		try {
			while (!socket.isClosed()) {
				String msg;

				// accept input from user, and send it to the outstream
				// of the socket, for the server to receive:
				msg = keyboardIn.readLine();
				out.println(msg);
			}

			// if socket is closed (for some reason), 
			// close the in and out streams
			in.close();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}


	}

	public void run() {

		String line = null;
		try {
			// listen to the in stream. If a non-null line is 
			// received analyze it and act appropriately
			while ( ( ( line = in.readLine() ) != null ) 
					&& !socket.isClosed(  ) ) {

				// read the first word of the line 
				// which corresponds to a command
				String command = (line.split(" ")[0]).toUpperCase();

				// if command is PRINT, information, don't preface message 
				if (command.equals("PRINT")) {
					System.out.println(line.substring(6));
					continue;
				}

				// The SERVER command instructs the thread to start the server side of the proxy
				if (command.equals("SERVER")) {
					String clientName = line.split(" ")[1]; 
					out.println("STARTED " + clientName);
					out.flush();
					continue;
				}
				
				// The CLIENT command instructs the thread to start the client side of the proxy
				if (command.equals("CLIENT")) {
					String serverName = line.split(" ")[1];
					String serverAddress = line.split(" ")[2];
					if (serverAddress.equals("localhost"))
						serverAddress = this.socket.getInetAddress().getHostName();
					JBPClientConnector clientConnector = new JBPClientConnector(serverAddress, serverName);
					System.out.println("Connected to " + serverName + ".");
					out.println("CONNECTED" + serverName);
					out.flush();
				}
				
				// if command is ERR, print the Error message.
				// NOTE: Error messages are marked separately from other
				// messages. This is not a current requirement, but 
				// the distinction may become useful with added functionality.
				if (command.equals("ERR")) {
					System.out.println(line.substring(4));
					continue;
				}

				// if command is EXT, disconnect.
				if (command.equals("EXT")) {
					System.out.println("Disconnected.");
					disconnect = true;
					out.close();
					in.close();
					socket.close();
					break;
				}
			}
		} catch (IOException e) {
			// In case of exception:
			e.printStackTrace();
		} catch (Exception e) {
			// In case of an exception:
			e.printStackTrace();
		}

		// If the server has disconnected:
		// (the variable disconnect is only true if 
		// the user requested to disconnect. Otherwise
		// assume that the server disconnected)
		if (!disconnect) {
			System.out.println("Server disconnected.");
			System.exit(1);
		}
	}
}